﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PracticeAzure.Website.Shared;
using PracticeAzure.Website.Models;
using PracticeAzure.Website.Data;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.IO;

namespace PracticeAzure.Website.Controllers
{
    public class CorrigendumController : PracticeAzureBaseController
    {
        [HttpGet]
        public ActionResult Index(int? page)
        {
            var model = new CorrigendumIndexViewModel();

            model.Corrigendums = Corrigendum.List(page);
            model.Count = Corrigendum.Count();
            model.Page = page ?? 1;

            return View(model);
        }

        [HttpGet]
        public ActionResult Details(long id, int? page)
        {
            var model = new CorrigendumDetailsViewModel();

            model.Corrigendum = Corrigendum.Load(id);
            model.Replies = CorrigendumReply.List(id, page);
            model.Attachments = CorrigendumAttachment.List(id);
            model.Count = model.Corrigendum.ReplyCount;
            model.Page = page ?? 1;

            return View(model);
        }

        [HttpGet]
        [Authorize]
        public ActionResult Create()
        {
            var model = new CorrigendumCreateViewModel();
            return View(model);
        }

        [HttpPost]
        [Authorize]
        [ValidateInput(false)]
        public ActionResult Create([ModelBinder(typeof(CorrigendumCreateViewModel.ModelBinder))]CorrigendumCreateViewModel model)
        {
            // validation
            if (ModelState.IsValid)
            {
                // insert the corrigendum into database
                var corrigendum = new Corrigendum()
                {
                    Title = model.Title,
                    Body = model.Body
                };
                corrigendum.Save();
                // prepare the azure blob service client
                var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
                var container = account.GetBlobContainerReference(GlobalConfiguration.AttachementContainerName, true);
                // add the attachements in blob
                var attachments = new List<CorrigendumAttachment>();
                foreach (var file in model.Attachments)
                {
                    // prepend the corrigendum id for each attachement file name
                    var blob = container.GetBlobReference(string.Format(GlobalConfiguration.AttachmentNameFormat, corrigendum.ID, Path.GetFileName(file.FileName)));
                    // remove the existing blob
                    blob.DeleteIfExists();
                    // upload the blob and retrieve the url
                    blob.UploadFromStream(file.InputStream, BlobHelperLite.DefaultRequestOptions);
                    attachments.Add(new CorrigendumAttachment()
                    {
                        CorrigendumID = corrigendum.ID,
                        ContentType = file.ContentType,
                        URL = blob.Uri.AbsoluteUri
                    });
                }
                // insert the attachement records
                CorrigendumAttachment.BatchSave(attachments);
                // back to the corrigendum list
                return RedirectToAction("Index");
            }
            else
            {
                return Create();
            }
        }

        [HttpGet]
        [Authorize]
        public ActionResult Edit(long id)
        {
            var corrigendum = Corrigendum.Load(id);
            var attachments = CorrigendumAttachment.List(id);

            var model = new CorrigendumEditViewModel()
            {
                Corrigendum = corrigendum,
                ExistingAttachments = attachments.Select((att) =>
                    {
                        return new CorrigendumEditViewModel.CorrigendumAttachmentWithState()
                        {
                            Attachment = att,
                            State = CorrigendumEditViewModel.CorrigendumAttachmentState.Original
                        };
                    })
            };
            return View(model);
        }

        [HttpPost]
        [Authorize]
        [ValidateInput(false)]
        public ActionResult Edit([ModelBinder(typeof(CorrigendumEditViewModel.ModelBinder))]CorrigendumEditViewModel model)
        {
            // validation
            if (ModelState.IsValid)
            {
                // update the corrigendum information
                model.Corrigendum.Save();
                // remove the attachments that had been deleted from the view
                var account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
                var container = account.GetBlobContainerReference(GlobalConfiguration.AttachementContainerName, true);
                foreach (var deletedAttachment in model.ExistingAttachments.Where(a => a.State == CorrigendumEditViewModel.CorrigendumAttachmentState.Deleted))
                {
                    if (!string.IsNullOrWhiteSpace(deletedAttachment.Attachment.URL))
                    {
                        var blob = container.GetBlobReference(deletedAttachment.Attachment.URL);
                        blob.DeleteIfExists();
                    }
                }
                // remove the attachment records
                CorrigendumAttachment.BatchDelete(model.ExistingAttachments
                    .Where(a => a.State == CorrigendumEditViewModel.CorrigendumAttachmentState.Deleted)
                    .Select(a => a.Attachment.ID)
                    .ToList());
                // upload the new attachments
                var newAttachmentEntities = new List<CorrigendumAttachment>();
                foreach (var file in model.NewAttachments)
                {
                    // prepend the corrigendum id for each attachement file name
                    var blob = container.GetBlobReference(string.Format(GlobalConfiguration.AttachmentNameFormat, model.Corrigendum.ID, Path.GetFileName(file.FileName)));
                    // remove the existing blob
                    blob.DeleteIfExists();
                    // upload the blob and retrieve the url
                    blob.UploadFromStream(file.InputStream, BlobHelperLite.DefaultRequestOptions);
                    newAttachmentEntities.Add(new CorrigendumAttachment()
                    {
                        CorrigendumID = model.Corrigendum.ID,
                        ContentType = file.ContentType,
                        URL = blob.Uri.AbsoluteUri
                    });
                }
                // insert the new attachment records
                CorrigendumAttachment.BatchSave(newAttachmentEntities);
                // back to the list page
                return RedirectToAction("Index");
            }
            else
            {
                return Edit(model.Corrigendum.ID);
            }
        }

        [HttpGet]
        [Authorize]
        [ActionName("Delete")]
        public ActionResult DeleteOnGet(long id)
        {
            var model = new CorrigendumDetailsViewModel();

            model.Corrigendum = Corrigendum.Load(id);
            model.Attachments = CorrigendumAttachment.List(id);

            return View(model);
        }

        [HttpPost]
        [Authorize]
        [ActionName("Delete")]
        public ActionResult DeleteOnPost(long id)
        {
            if (GlobalConfiguration.PermanentDelete)
            {
                // delete the corrigendum, replies, attachments and the blobs
                var attachments = CorrigendumAttachment.List(id);
                CorrigendumAttachment.BatchDelete(attachments.Select(a => a.ID));
                Corrigendum.Erase(id);
            }
            else
            {
                // only mark the corrigendum as delete
                Corrigendum.Delete(id);
            }
            return RedirectToAction("Index");
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult Reply(long id, string reply, string email)
        {
            if (GlobalConfiguration.AllowReply)
            {
                // encode the reply and email
                reply = HttpUtility.HtmlEncode(reply);
                email = HttpUtility.HtmlEncode(email);
                // validate
                if (string.IsNullOrWhiteSpace(reply))
                {
                    ModelState.AddModelError("reply", "请输入回复的内容。");
                    return Details(id, null);
                }
                // insert the reply record
                var corrigendumReply = new CorrigendumReply()
                {
                    CorrigendumID = id,
                    Body = reply,
                    CreatedByEmail = email
                };
                corrigendumReply.Reply();
            }
            return RedirectToAction("Details", new { id = id });
        }

        [HttpGet]
        [Authorize]
        public ActionResult Hide(long id, long corrigendumId)
        {
            CorrigendumReply.Hide(id);
            return RedirectToAction("Details", new { id = corrigendumId });
        }
    }
}
